"""
Microgrid Details BMS Report API

This module provides REST API endpoints for generating microgrid battery management system (BMS) reports.
It analyzes BMS data and performance metrics to provide insights into battery system
performance, health monitoring, and optimization opportunities.

Key Features:
- BMS performance analysis
- Battery health monitoring
- Performance metrics calculation
- System optimization insights
- Performance monitoring
- Battery system analysis

Report Components:
- BMS performance summary
- Battery health metrics
- Performance indicators
- System optimization recommendations
- Battery system analysis
- Performance trends

The module uses Falcon framework for REST API and includes:
- Database queries for BMS data
- Performance analysis algorithms
- Battery monitoring tools
- Multi-language support
- User authentication and authorization
"""

from datetime import datetime, timedelta
import falcon
import mysql.connector
import simplejson as json
from core.useractivity import access_control, api_key_control
import config


class Reporting:
    def __init__(self):
        """Initializes Class"""
        pass

    @staticmethod
    def on_options(req, resp, id_):
        _ = req
        resp.status = falcon.HTTP_200
        _ = id_

    ####################################################################################################################
    # PROCEDURES
    # Step 1: valid parameters
    # Step 2: query the microgrid
    # Step 3: query analog points latest values
    # Step 4: query energy points latest values
    # Step 5: query digital points latest values
    # Step 6: query the points of BMSes
    # Step 7: construct the report
    ####################################################################################################################
    @staticmethod
    def on_get(req, resp, id_):
        if 'API-KEY' not in req.headers or \
                not isinstance(req.headers['API-KEY'], str) or \
                len(str.strip(req.headers['API-KEY'])) == 0:
            access_control(req)
        else:
            api_key_control(req)

        ################################################################################################################
        # Step 1: valid parameters
        ################################################################################################################
        if not id_.isdigit() or int(id_) <= 0:
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
                                   description='API.INVALID_MICROGRID_ID')
        microgrid_id = id_
        ################################################################################################################
        # Step 2: query the microgrid
        ################################################################################################################
        cnx_system = mysql.connector.connect(**config.myems_system_db)
        cursor_system = cnx_system.cursor()

        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
        cursor_historical = cnx_historical.cursor()

        if microgrid_id is not None:
            query = (" SELECT id, name, uuid "
                     " FROM tbl_microgrids "
                     " WHERE id = %s ")
            cursor_system.execute(query, (microgrid_id,))
            row = cursor_system.fetchone()

        if row is None:
            cursor_system.close()
            cnx_system.close()
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
                                   description='API.MICROGRID_NOT_FOUND')

        # query all points
        query = (" SELECT id, name, units, description "
                 " FROM tbl_points ")
        cursor_system.execute(query)
        rows = cursor_system.fetchall()

        points_dict = dict()
        if rows is not None and len(rows) > 0:
            for row in rows:
                points_dict[row[0]] = [row[1], row[2], row[3]]

        ################################################################################################################
        # Step 3: query analog points latest values
        ################################################################################################################

        latest_value_dict = dict()
        query = (" SELECT point_id, actual_value "
                 " FROM tbl_analog_value_latest "
                 " WHERE utc_date_time > %s ")
        cursor_historical.execute(query, (datetime.utcnow() - timedelta(minutes=60),))
        rows = cursor_historical.fetchall()
        if rows is not None and len(rows) > 0:
            for row in rows:
                latest_value_dict[row[0]] = [points_dict[row[0]][0],
                                             points_dict[row[0]][1],
                                             points_dict[row[0]][2],
                                             row[1]]

        ################################################################################################################
        # Step 4: query energy points latest values
        ################################################################################################################
        query = (" SELECT point_id, actual_value "
                 " FROM tbl_energy_value_latest "
                 " WHERE utc_date_time > %s ")
        cursor_historical.execute(query, (datetime.utcnow() - timedelta(minutes=60),))
        rows = cursor_historical.fetchall()
        if rows is not None and len(rows) > 0:
            for row in rows:
                latest_value_dict[row[0]] = [points_dict[row[0]][0],
                                             points_dict[row[0]][1],
                                             points_dict[row[0]][2],
                                             row[1]]

        ################################################################################################################
        # Step 5: query digital points latest values
        ################################################################################################################
        query = (" SELECT point_id, actual_value "
                 " FROM tbl_digital_value_latest "
                 " WHERE utc_date_time > %s ")
        cursor_historical.execute(query, (datetime.utcnow() - timedelta(minutes=60),))
        rows = cursor_historical.fetchall()
        if rows is not None and len(rows) > 0:
            for row in rows:
                latest_value_dict[row[0]] = [points_dict[row[0]][0],
                                             points_dict[row[0]][1],
                                             points_dict[row[0]][2],
                                             row[1]]

        ################################################################################################################
        # Step 6: query the points of associated BMSes
        ################################################################################################################

        bms_list = list()
        cursor_system.execute(" SELECT id, name, uuid "
                              " FROM tbl_microgrids_batteries "
                              " WHERE microgrid_id = %s "
                              " ORDER BY id ",
                              (microgrid_id,))
        rows_bmses = cursor_system.fetchall()
        if rows_bmses is not None and len(rows_bmses) > 0:
            for row in rows_bmses:
                current_bms = dict()
                current_bms['id'] = row[0]
                current_bms['name'] = row[1]
                current_bms['uuid'] = row[2]
                current_bms['points'] = list()
                bms_list.append(current_bms)
        print(bms_list)
        for index, bms in enumerate(bms_list):
            cursor_system.execute(" SELECT p.id "
                                  " FROM tbl_microgrids_bmses_points bp, tbl_points p "
                                  " WHERE bp.bms_id = %s AND bp.point_id = p.id "
                                  " ORDER BY bp.id ",
                                  (bms['id'],))
            rows_points = cursor_system.fetchall()
            if rows_points is not None and len(rows_points) > 0:
                point_list = list()
                for row in rows_points:
                    point = latest_value_dict.get(row[0], None)
                    if point is not None:
                        point_list.append(point)
                bms_list[index]['points'] = point_list

        if cursor_system:
            cursor_system.close()
        if cnx_system:
            cnx_system.close()

        if cursor_historical:
            cursor_historical.close()
        if cnx_historical:
            cnx_historical.close()
        ################################################################################################################
        # Step 8: construct the report
        ################################################################################################################
        resp.text = json.dumps(bms_list)
